﻿using FluentAssertions;
using Masuit.Tools;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NewRetail.Application.Components.PrintTask;
using NewRetail.Application.Components.PrintTask.Entity;
using NewRetail.Application.Components.PrintTask.Model;
using NewRetail.Application.Components.Warehouse;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using NewRetail.Application.Core.Entity;
using NewRetail.Application.Utility;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;

namespace NewRetail.Api.Controllers
{
    [NewRetailRoute("inout-warehousing")]
    public class InOutWarehousingController : BaseController<InOutWarehousing, InOutWarehousePagingDto>
    {
        private readonly IWarehouseGoodsService warehouseGoodsService;
        private readonly IInOutWarehouseService inOutWarehouseService;
        private readonly IPrintTaskService printTaskService;

        public InOutWarehousingController(
            IWarehouseGoodsService warehouseGoodsService,
            IInOutWarehouseService inOutWarehouseService,
            IPrintTaskService printTaskService)
        {
            this.warehouseGoodsService = warehouseGoodsService;
            this.inOutWarehouseService = inOutWarehouseService;
            this.printTaskService = printTaskService;
        }

        [HttpPost("query-statistics-summary")]
        public async Task<ResponseEntity<QueryInOutWarehouseSummaryGroupResult[]>> QueryStatisticsSummary(QueryInOutWarehouseSummaryGroupDto dto)
        {
            var data = await this.inOutWarehouseService.QueryStatisticsSummary(dto);
            return new ResponseEntity<QueryInOutWarehouseSummaryGroupResult[]>().SetData(data);
        }

        [HttpPost("query-statistics-detail")]
        public async Task<ResponseEntity<QueryInOutWarehouseDetailGroupResult[]>> QueryStatisticsDetail(QueryInOutWarehouseDetailGroupDto dto)
        {
            var data = await this.inOutWarehouseService.QueryStatisticsDetail(dto);
            return new ResponseEntity<QueryInOutWarehouseDetailGroupResult[]>().SetData(data);
        }

        protected override async Task<IQueryable<InOutWarehousing>> FilterQueryPaging(DbContext db, IQueryable<InOutWarehousing> query, InOutWarehousePagingDto dto)
        {
            if (dto.InOrOut != null)
            {
                query = query.Where(x => x.inOrOut == dto.InOrOut.Value);
            }

            if (!string.IsNullOrWhiteSpace(dto.warehouseId))
            {
                query = query.Where(x => x.warehouseID == dto.warehouseId);
            }

            query = query.WhereIf(!string.IsNullOrWhiteSpace(dto.supplierId), x => x.supplierID == dto.supplierId);

            if (dto.isAuditing != null)
            {
                query = query.Where(x => x.isAuditing == dto.isAuditing.Value);
            }

            #region add by cl 20240903
            query = query.WhereIf(dto.startTime != null, x => x.receiptDate >= dto.startTime.Value);
            query = query.WhereIf(dto.endTime != null, x => x.receiptDate < dto.endTime.Value);
            #endregion

            await Task.CompletedTask;
            return query;
        }

        public override async Task<ResponseEntity<PagedResultDto<InOutWarehousing>>> QueryPaging([FromBody] InOutWarehousePagingDto dto)
        {
            var res = await base.QueryPaging(dto);

            if (res.Data?.Items?.Any() ?? false)
            {
                res.Data.Items = await this.inOutWarehouseService.AttachGoodsInfo(res.Data.Items.ToArray());
                res.Data.Items = await this.inOutWarehouseService.AttachSupplier(res.Data.Items.ToArray());
                res.Data.Items = await this.inOutWarehouseService.AttachWarehouse(res.Data.Items.ToArray());
            }

            return res;
        }

        [HttpPost("add-multiple"), Obsolete]
        public async Task<ResponseEntity<InOutWarehousing[]>> AddMultiple([FromBody] InOutWarehousing[] data)
        {
            data.Should().NotBeNullOrEmpty();
            var no = await this.NoGeneratorService.GenerateReceiptNoAsync("IO");
            foreach (var m in data)
            {
                this.EntityHelper.InitEntity(m);
                m.receiptNo = no;
                m.isAuditing = false;
            }

            await this.Repo.InsertManyAsync(data, autoSave: true);

            return new ResponseEntity<InOutWarehousing[]>().SetData(data);
        }

        /// <summary>
        /// 每条入库单只显示一条记录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("query-paging-distinct")]
        public async Task<ResponseEntity<PagedResultDto<InOutWarehousing>>> QueryPagingDistinct([FromBody] InOutWarehousePagingDto dto)
        {
            var query = await base.GetQueryPagingData(dto);
            var data = new PagedResultDto<InOutWarehousing>();
            query = await this.OrderQueryPaging(query, dto);

            #region add by cl 2022.08.15
            query = query.WhereIf(dto.startTime != null, x => x.receiptDate >= dto.startTime.Value);
            query = query.WhereIf(dto.endTime != null, x => x.receiptDate < dto.endTime.Value);
            #endregion

            var list = query.ToList().GroupBy(g => new { g.receiptDate, g.receiptNo, g.warehouseID, g.supplierID, g.inOrOut })
                .Select(x => new InOutWarehousing
                {
                    receiptDate = x.Key.receiptDate,
                    receiptNo = x.Key.receiptNo,
                    warehouseID = x.Key.warehouseID,
                    supplierID = x.Key.supplierID,
                    inOrOut = x.Key.inOrOut,
                    quantity = x.Sum(s => s.quantity),
                    price = x.Sum(s => s.price * s.quantity),//由于字段中没有对应金额参数，因此这边借用price字段供前端显示金额列
                    grossProfit = x.Sum(s => s.grossProfit),
                    isAuditing = x.Select(a => a.isAuditing).FirstOrDefault(),
                    operateTime = x.Select(a => a.operateTime).FirstOrDefault()
                }).ToList();

            //logger.LogInformation(">>>>>>>>>>>>>>>>>>Count:" + query.Count());
            //去重(同一批次的入库单单号相同)
            //var list = query.ToList().Distinct(new InOutWarehousingComparer()).ToList();
            //query = query.GroupBy(io => new { io.receiptDate, io.receiptNo, io.Id, io.warehouseID, io.supplierID }).Select(io => io.First());

            data.TotalCount = list.Count();
            //logger.LogInformation(">>>>>>>>>>>>>>>>>>TotalCount：" + data.TotalCount);
            list = list.Skip((dto.Page - 1) * dto.PageSize).Take(dto.PageSize).ToList();
            //logger.LogInformation(">>>>>>>>>>>>>>>>>>5");
            data.Items = list.ToArray();
            ResponseEntity<PagedResultDto<InOutWarehousing>> res = new ResponseEntity<PagedResultDto<InOutWarehousing>>().SetData(data);

            if (res.Data?.Items?.Any() ?? false)
            {
                res.Data.Items = await this.inOutWarehouseService.AttachSupplier(res.Data.Items.ToArray());
                res.Data.Items = await this.inOutWarehouseService.AttachWarehouse(res.Data.Items.ToArray());
            }

            return res;
        }

        [HttpPost("save-multiple")]
        public async Task<ResponseEntity<InOutWarehousing[]>> SaveMultiple([FromBody] ReceiptNoItemsDto<InOutWarehousing> data)
        {
            var res = await this.Repo.SaveReceiptItems(this.HttpContext.RequestServices, data, "IO");
            return new ResponseEntity<InOutWarehousing[]>().SetData(res.Items);
        }


        [HttpPost("query-by-receipt-no")]
        public async Task<ResponseEntity<InOutWarehousing[]>> QueryByReceiptNo([FromBody] ReceiptNoDto dto)
        {
            dto.Should().NotBeNull();
            dto.receiptNo.Should().NotBeNullOrEmpty();
            var query = this.SingleStoreService.ApplyToQueryable(this.Repo);
            var data = await query.Where(x => x.receiptNo == dto.receiptNo).ToArrayAsync();

            data = await this.inOutWarehouseService.AttachGoodsInfo(data);
            data = await this.inOutWarehouseService.AttachSupplier(data);
            data = await this.inOutWarehouseService.AttachWarehouse(data);
            data = data.OrderBy(x => x.GoodsInfo?.No).ToArray();
            //打印时候合并货号显示
            if (!string.IsNullOrWhiteSpace(dto.sType) && dto.sType == "0")
            {
                //add 20240617 cl  根据货号合并
                var result = data.GroupBy(g => new
                {
                    g.receiptNo,
                    g.receiptDate,
                    g.supplierID,
                    g.warehouseID,
                    g.inOrOut,
                    g.GoodsInfo.goodsCode,
                    g.goodsName
                })
                    .Select(s => new InOutWarehousing
                    {
                        receiptDate = s.Key.receiptDate,
                        receiptNo = s.Key.receiptNo,
                        supplierID = s.Key.supplierID,
                        warehouseID = s.Key.warehouseID,
                        inOrOut = s.Key.inOrOut,
                        goodsName = s.Key.goodsName,
                        GoodsInfo = s.Select(d => d.GoodsInfo).FirstOrDefault(),
                        Supplier = s.Select(d => d.Supplier).FirstOrDefault(),
                        Warehouse = s.Select(d => d.Warehouse).FirstOrDefault(),
                        quantity = s.Sum(x => x.quantity),
                        price = s.Average(x => x.price),
                        curSalePrice = s.Average(x => x.curSalePrice),
                        grossProfit = s.Average(x => x.grossProfit),
                        remarkMst = s.Max(x => x.remarkMst)
                    }).ToArray();
                return new ResponseEntity<InOutWarehousing[]>().SetData(result);
            }
            return new ResponseEntity<InOutWarehousing[]>().SetData(data);
        }

        [HttpPost("save-print-task")]
        public async Task<ResponseEntity<string>> SavePrintTask([FromBody] ReceiptNoDto dto)
        {
            dto.Should().NotBeNull();
            dto.receiptNo.Should().NotBeNullOrEmpty();
            var query = this.SingleStoreService.ApplyToQueryable(this.Repo);
            var data = await query.Where(x => x.receiptNo == dto.receiptNo).FirstOrDefaultAsync();
            var printTaskSaveData = new PrintTaskSaveInputDto
            {
                receiptDate = data.receiptDate,
                receiptNo = data.receiptNo,
                printTag = 0,
                printNo = "P0"
            };


            var ret = new ResponseEntity<string>();
            try
            {
                var result = await this.printTaskService.SavePrintTaskItems(printTaskSaveData);
                if (result.Item1 == 0)
                    ret.SetError("创建打印任务失败！" + result.Item2);
                ret.SetData("创建打印任务成功");
            }
            catch (Exception e)
            {
                ret.SetError("创建失败！" + e.Message);
                //logger.LogError(e.Message);
            }

            return ret;
        }

        #region add by cl 20221214
        /// <summary>
        /// 整单删除得根据receiptNo找到id
        /// </summary>
        /// <param name="ids">receiptNo数组</param>
        /// <returns></returns>
        protected override async Task<string[]> BeforeDelete(string[] ids)
        {
            string[] delIds = null;

            if (ids.Length > 0)
            {
                var query = this.SingleStoreService.ApplyToQueryable(this.Repo);
                //找出未审核的单据
                delIds = await query.Where(g => ids.Contains(g.receiptNo) && g.isAuditing == false).Select(g => g.Id).Distinct().ToArrayAsync();
            }
            if (delIds.Length == 0)
            {
                throw new UserFriendlyException("没有要删除的记录！");
            }

            return delIds;
        }
        #endregion

        #region 采购入库/退货统计(供移动端掌售通使用)
        [HttpPost("query-mobile-home-order-summary")]
        public async Task<ResponseEntity<QueryMobileInOutWarehouseSummaryGroupResult[]>> QueryMobileHomeOrderSummary([FromBody] QueryInOutWarehouseSummaryGroupDto dto)
        {
            var data = await this.inOutWarehouseService.QueryMobileHomeOrderSummary(dto);
            return new ResponseEntity<QueryMobileInOutWarehouseSummaryGroupResult[]>().SetData(data);
        }
        #endregion
    }
}
